package com.eastidea.live.controller.mobi;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.collections.map.LinkedMap;
import org.bson.types.ObjectId;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.eastidea.live.dao.AppDao;
import com.eastidea.live.dao.FormDao;
import com.eastidea.live.dao.FormDataDao;
import com.eastidea.live.dao.UserDao;
import com.eastidea.live.entity.AppApplication;
import com.eastidea.live.entity.AppUser;
import com.eastidea.live.entity.FrmDtData;
import com.eastidea.live.entity.FrmInfMultipleChoice;
import com.eastidea.live.entity.FrmInfMultipleOptions;
import com.eastidea.live.entity.FrmInfSingleLineText;
import com.eastidea.live.entity.FrmUiField;
import com.eastidea.live.entity.FrmUiForm;
import com.eastidea.live.field.multiplechoice.MultipleChoiceDao;
import com.eastidea.live.field.multiplechoice.MultipleChoiceOptionsDao;
import com.eastidea.live.field.multiplechoice.MultipleChoiceOptionsTo;
import com.eastidea.live.field.multiplechoice.MultipleChoiceOt;
import com.eastidea.live.field.multiplechoice.MultipleChoiceService;
import com.eastidea.live.field.multiplechoice.MultipleChoiceTo;
import com.eastidea.live.field.pagebreak.PageBreakOt;
import com.eastidea.live.field.pagebreak.PageBreakService;
import com.eastidea.live.field.pagebreak.PageBreakTo;
import com.eastidea.live.field.singleline.SingleLineTextDao;
import com.eastidea.live.field.singleline.SingleLineTextOt;
import com.eastidea.live.field.singleline.SingleLineTextService;
import com.eastidea.live.field.singleline.SingleLineTextTo;
import com.eastidea.live.ot.AppOt;
import com.eastidea.live.ot.FormOt;
import com.eastidea.live.service.FieldService;
import com.eastidea.live.service.FormService;
import com.eastidea.live.to.AppTo;
import com.eastidea.live.to.FieldTo;
import com.eastidea.live.to.FormTo;
import com.eastidea.live.util.DateTimeUtil;
import com.eastidea.live.util.QrUtil;
import com.eastidea.live.util.RequestUtil;
import com.eastidea.live.util.StringUtil;
import com.eastidea.live.util.Constant;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;

@Controller
@SessionAttributes("user")
@RequestMapping(value = Constant.API_REST_V1 + "/form/")
public class FormController {

	@Resource
	AppDao appDao;

	@Resource
	FormDao formDao;
	@Resource
	FormDataDao dataDao;

	@Resource
	FormService formService;
	@Resource
	FieldService fieldService;
	
	@RequestMapping(value = "data/{formId}", method = RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> data(@ModelAttribute("user") AppUser user, @PathVariable("formId") String formId,
			HttpServletRequest request) throws UnknownHostException {
		Map<String, Object> res = new HashMap<String, Object>();
		
		Long userId = user.getId();
		if (userId == null) {
			res.put("success", false);
			return res;
		}
		
		Mongo mongo = new Mongo();
		DB db = mongo.getDB("palmio");
		boolean auth = db.authenticate("admin", "P2ssw0rd".toCharArray());
		System.out.println("auth: "+auth);
		DBCollection forms = db.getCollection("data");
		DBObject queryCondition = new BasicDBObject();
	    queryCondition.put("formId", formId);	    
		DBCursor cur = forms.find(queryCondition).sort(new BasicDBObject("submitTime", -1));
		List<DBObject> ls = cur.toArray();
		
		BasicDBList nameList = new BasicDBList();
		BasicDBList uidList = new BasicDBList();
		BasicDBList valList = new BasicDBList();
		
		nameList.add("submitTime");
		nameList.add("ipAddr");
		for (DBObject dt: ls) {
			String submitTime = DateTimeUtil.ToTimeStr((Date)dt.get("submitTime"));
			String ipAddr = dt.get("ipAddr").toString();
			
			BasicDBObject v = new BasicDBObject();
			v.put("submitTime", submitTime);
			v.put("ipAddr", ipAddr);
			
			for (Object val: (BasicDBList)dt.get("values")) {				
				BasicDBObject valObj = (BasicDBObject)val;			
				String uid = valObj.get("uid").toString();
				String name = valObj.get("name").toString();
				String value = valObj.get("value").toString();
				
				v.put(name,  value);				
				if (!uidList.contains(uid)) {
					nameList.add(name);
					uidList.add(uid);
				}
			}
			valList.add(v);
		}
		
		List<String> th = new ArrayList<String>();
		for (Object name: nameList) {			
			th.add(name.toString());
		}		
		List<List<Object>> trs = new ArrayList<List<Object>>();
		for (Object val: valList) {
			BasicDBObject valObj = (BasicDBObject)val;	
			
			List<Object> tr = new ArrayList<Object>();
			for (Object name: nameList) {			
				tr.add(valObj.get(name));
			}
			trs.add(tr);
		}

		res.put("id", formId);
		res.put("th", th);
		res.put("trs", trs);
		res.put("email", user.getEmail());
		return res;
	}

	@RequestMapping(value = "report/{formId}", method = RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> report(@ModelAttribute("user") AppUser user, @PathVariable("formId") String formId,
			HttpServletRequest request) throws UnknownHostException {
		Map<String, Object> res = new HashMap<String, Object>();

		Long userId = user.getId();
		if (userId == null) {
			res.put("success", false);
			return res;
		}
		
		Mongo mongo = new Mongo();
		DB db = mongo.getDB("palmio");
		boolean auth = db.authenticate("admin", "P2ssw0rd".toCharArray());
		System.out.println("auth: "+auth);
		DBCollection dataCon = db.getCollection("data");
		DBObject queryCondition = new BasicDBObject();
	    queryCondition.put("formId", formId);	    
		DBCursor cur = dataCon.find(queryCondition).sort(new BasicDBObject("submitTime", 1));
		List<DBObject> ls = cur.toArray();
		
		Map<String,String> nameMap = new HashMap<String,String>();
		Map<String, Map<String, Integer>> reportMap = new HashMap<String, Map<String, Integer>>();
		for (DBObject dt: ls) {			
			for (Object val: (BasicDBList)dt.get("values")) {
				BasicDBObject valObj = (BasicDBObject)val;
				String type = valObj.get("type").toString();
				if (type.equals("multipleChoice") || type.equals("dropdown")) {
					String uid = valObj.get("uid").toString();
					String name = valObj.get("name").toString();
					String value = valObj.get("value").toString();

					nameMap.put(uid, name); // will be set to the last one
					if (!reportMap.containsKey(uid)) {
						reportMap.put(uid, new HashMap<String, Integer>());
					}
					Map<String, Integer> filedMap = reportMap.get(uid);
					if (!filedMap.containsKey(value)) {
						filedMap.put(value, 0);
					}
					filedMap.put(value, filedMap.get(value) + 1);
				} else if (type.equals("checkboxes")) {
					String uid = valObj.get("uid").toString();
					String name = valObj.get("name").toString();
					String value = valObj.get("value").toString();
					nameMap.put(uid, name); // will be set to the last one
					if (!reportMap.containsKey(uid)) {
						reportMap.put(uid, new HashMap<String, Integer>());
					}
					Map<String, Integer> filedMap = reportMap.get(uid);
					
					for (String v : value.split(",")) {
						if (!filedMap.containsKey(v)) {
							filedMap.put(v, 0);
						}
						filedMap.put(v, filedMap.get(v) + 1);
					}
				}
			}
		}

		BasicDBList names = new BasicDBList();
		BasicDBList data = new BasicDBList();
		BasicDBList ticks = new BasicDBList();
		for (String uid : reportMap.keySet()) {			
			BasicDBList t = new BasicDBList();
			BasicDBList d = new BasicDBList();
			Map<String, Integer> fMap = reportMap.get(uid);
			for (String option : fMap.keySet()) {
				t.add(option);
				d.add(fMap.get(option));
			}
			names.add(nameMap.get(uid));
			ticks.add(t);
			data.add(d);
		}
		
		res.put("id", formId);
		res.put("names", names);		
		res.put("ticks", ticks);
		res.put("data", data);
		res.put("email", user.getEmail());
		return res;
	}
}
